#pragma once
#ifndef CHANNEL_H
#define CHANNEL_H
#include "NonCopyable.h"
#include <functional> 
#include "TimeStamp.h"
#include <memory>
namespace mymuduo {

// 头文件给出类型前置声明，源文件包含具体头文件，减少对外暴露的头文件信息
class EventLoop;

/*
 * 理清楚 EventLoop，Channel，Poller 之间的关系，Channel 在 Reactor 模型上对应 Demultiplex
 * Channel 理解为通道，封装了 socketfd 和其感兴趣的 event，如EPOLLIN，EPOLLOUT 事件
 * 还绑定了 poller 返回的具体事件
 */
class Channel : NonCopyable {
public:
    // std::function对象是对C++中现有的可调用实体的一种类型安全的包裹，std::function对象最大的用处就是在实现函数回调
    using ReadEventCallback = std::function<void(TimeStamp)>;
    using EventCallback = std::function<void()>;

    Channel(EventLoop *loop, int fd);
    ~Channel();

    // fd 得到 poller 通知后，处理事件的方法
    void handleEvent(TimeStamp recieveTime);

    // 设置回调函数对象
    void setReadCallback(ReadEventCallback cb) {readCallback_ = std::move(cb);}
    void setWriteCallback(EventCallback cb) {writeCallback_ = std::move(cb);}
    void setCloseCallback(EventCallback cb) {closeCallback_ = std::move(cb);}
    void setErrorCallback(EventCallback cb) {errorCallback_ = std::move(cb);}

    // 防止当 channel 被手动 remove 掉，channel 还在执行回调操作
    void tie(const std::shared_ptr<void>&);
    
    int fd() const {return fd_;}
    int event() const {return events_;}
    void setRevents(int revt) {revents_ = revt;}

    // 设置 fd 相应的事件状态
    void enableReading() {events_ |= kReadEvent; update();} 
    void disableReading() {events_ &= ~kReadEvent; update();}
    void enableWriting() { events_ |= kWriteEvent; update(); }
    void disableWriting() { events_ &= ~kWriteEvent; update(); }
    void disableAll() { events_ = kNoneEvent; update(); }

    // 返回 fd 当前的事件状态
    bool isNoneEvent() const {return events_ == kNoneEvent;} // 当前 channel 到底有没有注册感兴趣事件
    bool isWriting() const { return events_ & kWriteEvent; }
    bool isReading() const { return events_ & kReadEvent; }

    int index() { return index_; }
    void set_index(int idx) { index_ = idx; }

    // one loop per thread
    // 一个线程有一个 eventloop，一个 eventloop 有一个 poller，一个 poller 有多个 channel
    EventLoop* ownerLoop() { return loop_; }
    void remove();
  
private:   

    void handleEventWithGuard(TimeStamp recieveTime);
    void update();

    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop *loop_; // 事件循环
    const int fd_; // fd，Poller 监听的对象
    int events_; // 注册 fd 感兴趣的事件
    int revents_; // poller 返回的具体发生的事件
    int index_; // 指示 channel 的状态

    std::weak_ptr<void> tie_; // 多线程里面监听资源的生存状态，使用时提生成强智能指针，成功才访问
    bool tied_;

    // 因为 Channel 通道内能够获知 fd 最终发生的具体的事件 revents，所以他负责调用具体事件的回调操作
    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};

}

#endif